#pragma once

#include "String.h"
#include "UserInfo.h"
#include "rsa.h"

class Message
{
private:
	//UserInfo ui;

	AStr Head;
	AStr Content;

	AStr GenHexStr(int l,bool ucase = false)
	{
		l = (l+3)/4;
		AStr res,t;
		srand(GetTickCount());
		while(l-- > 0)
		{
			t = jPrintf((ucase)?"%04X":"%04x",(rand()+0x100)&0xFFFF);
			res.assign(*t,4,true);
		}
		return res;
	}
	
	AStr FxEncrypt(AStr userid, AStr password, AStr key, AStr nonce)
	{
		int u = atoi(userid);
		char * cu = (char*)&u;
		AStr tmp,res;
		tmp.assign(cu,4);
		res = SHA1("fetion.com.cn:" + password);
		tmp.assign(res,res.length(),true);
		res = SHA1(tmp);
		
		AStr aeskey = Hex2Bin(GenHexStr(64,true));
		
		tmp.assign(*nonce,nonce.length());
		tmp.assign(*res,res.length(),true);
		tmp.assign(*aeskey,aeskey.length(),true);
		
		private_key rsa;
		return to_hexstr(rsa.pkcs1_encrypt(tmp,key.mid(256),key.left(256),128));
	}

	void AddHeader(AStr line)
	{
		Head += line+"\r\n";
	}
	void SetContent(AStr content)
	{
		Content = content;
	}
	AStr Send()
	{
		return Head+"L: "+i2s(Content.length())+"\r\n\r\n"+Content;
	}
	void Clear()
	{
		Head.clear();
		Content.clear();
	}
public:

	Message(){ }

	AStr flag() { return Head.get("Q: ","\r\n",1); }
	
	AStr r1(UserInfo ui)
	{
		return r1(ui.fxno);
	}

	AStr r1(AStr fxno) //register to fxion server step 1
	{
		Clear();
		AddHeader("R fetion.com.cn SIP-C/4.0");
		AddHeader("F: "+fxno);
		AddHeader("I: 1");
		AddHeader("Q: 1 R");
		AddHeader("CN: "+GenHexStr(32));
		AddHeader("CL: type=\"pc\" ,version=\"4.2.1360\"");
		
		return Send();
	}
	
	AStr r2(UserInfo ui,AStr msg) // register to fxion server step 2
	{
		Clear();
		AddHeader("R fetion.com.cn SIP-C/4.0");
		AddHeader("F: "+ui.fxno);
		AddHeader("I: 1");
		AddHeader("Q: 2 R");
		AddHeader("A: Digest algorithm=\"SHA1-sess-v4\",response=\""+FxEncrypt(ui.uid,ui.pwd,msg.get("key=\"","\""),msg.get("nonce=\"","\""))+"\"");
		
		SetContent("<args><device accept-language=\"default\" machine-code=\"215D92DBC876FB23C80FE2EDB4BDFDF5\" /><caps value=\"1FFF\" /><events value=\"7F\" /><user-info mobile-no=\""+ui.mobileno+"\" user-id=\""+ui.uid+"\"><personal version=\"0\" attributes=\"v4default;alv2-version;alv2-warn\" /><custom-config version=\"0\" /><contact-list version=\"0\" buddy-attributes=\"v4default\" /></user-info><credentials domains=\"fetion.com.cn;m161.com.cn;www.ikuwa.cn;games.fetion.com.cn;turn.fetion.com.cn\" /><presence><basic value=\"400\" desc=\"\" /><extendeds /></presence></args>");
		return Send();
	}

	AStr r2_v(AStr pid, AStr vc)
	{
		AddHeader("A: Verify algorithm=\"picc-PasswordErrorMax\",type=\"GeneralPic\",response=\""+vc+"\",chid=\""+pid+"\"");
		return Send();
	}
	AStr m(AStr uri,int i,int q, AStr msg) // send msg
	{
		Clear();
		AddHeader("M fetion.com.cn SIP-C/4.0");
		AddHeader("F: "+uri);
		AddHeader("I: "+i2s(i));
		AddHeader("Q: "+i2s(q)+" M");
		AddHeader("C: text/plain");
		//AddHeader("C: text/html-fragment");//plain/html-fragment
		AddHeader("K: SaveHistory");
		SetContent(msg);
		return Send();
	}
	
	AStr sms(AStr fxno,int i, AStr dst, AStr msg) //send cat sms
	{
		Clear();
		AddHeader("M fetion.com.cn SIP-C/4.0");
		AddHeader("F: "+fxno);
		AddHeader("I: "+i2s(i));
		AddHeader("Q: 1 M");
		AddHeader("T: "+dst);
		AddHeader("N: SendCatSMS");
		SetContent(msg);
		return Send();
	}
	
	AStr gci(AStr fxno,int i,int q,AStr f) //get contact info
	{
		Clear();
		AddHeader("S fetion.com.cn SIP-C/4.0");
		AddHeader("F: "+fxno);
		AddHeader("I: "+i2s(i));
		AddHeader("Q: "+i2s(q)+" S");
		AddHeader("N: GetContactInfoV4");
		
		SetContent("<args><contact "+f+" /></args>");
		return Send();
	}

	AStr PGGetGroupList(AStr fxno,int i, int q)
	{
		Clear();
		AddHeader("S fetion.com.cn SIP-C/4.0");
		AddHeader("F: "+fxno);
		AddHeader("I: "+i2s(i));
		AddHeader("Q: "+i2s(q)+" S");
		AddHeader("N: PGGetGroupList");

		SetContent("<args><group-list /></args>");
		return Send();
	}

	AStr SetPresenceV4(AStr fxno,int i, int q)
	{
		Clear();
		AddHeader("S fetion.com.cn SIP-C/4.0");
		AddHeader("F: "+fxno);
		AddHeader("I: "+i2s(i));
		AddHeader("Q: "+i2s(q)+" S");
		AddHeader("N: SetPresenceV4");

		SetContent("<args><presence><extendeds><extended type=\"rtm\" /></extendeds></presence></args>");
		return Send();
	}

	AStr SGGetGroupList(AStr fxno,int i, int q)
	{
		Clear();
		AddHeader("S fetion.com.cn SIP-C/4.0");
		AddHeader("F: "+fxno);
		AddHeader("I: "+i2s(i));
		AddHeader("Q: "+i2s(q)+" S");
		AddHeader("N: SGGetGroupList");

		SetContent("<args><group-list version=\"0\" /></args>");
		return Send();
	}

	AStr PGSetPresence(AStr fxno,int i, int q)
	{
		Clear();
		AddHeader("S fetion.com.cn SIP-C/4.0");
		AddHeader("F: "+fxno);
		AddHeader("I: "+i2s(i));
		AddHeader("Q: "+i2s(q)+" S");
		AddHeader("N: PGSetPresence");

		SetContent("<args><groups /></args>");
		return Send();
	}


	AStr sub(AStr fxno,int i,int q) //sub all
	{
		Clear();
		AddHeader("SUB fetion.com.cn SIP-C/4.0");
		AddHeader("F: "+fxno);
		AddHeader("I: "+i2s(i));
		AddHeader("Q: "+i2s(q)+" SUB");
		AddHeader("N: PresenceV4");
		
		SetContent("<args><subscription self=\"v4default;mail-count;impresa;sms-online-status;feed-version;feed-type;es2all\" buddy=\"v4default;feed-version;feed-type;es2all;email-enable;rtm;dynamic-title;dynamic-id\" version=\"\" /></args>");
		//SetContent("<args><subscription self=\"v4default;mail-count;impresa\" buddy=\"v4default;multi-client;\" version=\"\" /></args>");
		return Send();
	}

	AStr i_o(AStr msg) //Invite response
	{
		Clear();
		AddHeader("SIP-C/4.0 200 OK");
		AddHeader("I: "+msg.get("I: ","\r\n"));
		AddHeader("Q: "+msg.get("Q: ","\r\n"));
		AddHeader("F: "+msg.get("F: ","\r\n"));
		return Send();
	}

	AStr ir(AStr msg, int &i,int &q) //Invite register to server
	{
		Clear();
		i = msg.get("I: ","\r\n").toi();
		q = 1;
		AddHeader("R fetion.com.cn SIP-C/4.0");
		AddHeader("F: "+msg.get("I "," SIP-C"));
		AddHeader("I: "+i2s(i));
		AddHeader("Q: 1 R");
		AddHeader("A: TICKS auth=\""+msg.get("credential=\"","\"")+"\"");
		AddHeader("K: text/plain");
		//AddHeader("K: text/html-fragment");
		AddHeader("K: multiparty");
/*
		AddHeader("K: nudge");
		AddHeader("K: share-background");
		AddHeader("K: fetion-show");
		AddHeader("K: ExModulesApp");
		AddHeader("K: FileTransferV4");
*/
		return Send();
	}

	AStr o(int i,int q, AStr dst) //option
	{
		Clear();
		AddHeader("O "+dst+" SIP-C/4.0");
		AddHeader("I: "+i2s(i));
		AddHeader("Q: "+i2s(q)+" O");
		AddHeader("K: text/plain");
		//AddHeader("C: text/html-fragment");
		AddHeader("K: multiparty");
		return Send();
	}

	AStr or(AStr msg) //Option response
	{
		Clear();
		AddHeader("SIP-C/4.0 200 OK");
		AddHeader("I: "+msg.get("I: ","\r\n"));
		AddHeader("Q: "+msg.get("Q: ","\r\n"));
		AddHeader("K: text/plain");
		//AddHeader("C: text/html-fragment");
		AddHeader("K: multiparty");
		return Send();
	}

	AStr mr(AStr msg) //Message response
	{
		Clear();
		AddHeader("SIP-C/4.0 200 OK");
		AddHeader("I: "+msg.get("I: ","\r\n"));
		AddHeader("Q: "+msg.get("Q: ","\r\n"));
		AddHeader("F: "+msg.get("F: ","\r\n"));
		return Send();
	}

	AStr sc(AStr fxno,int i) //StartChat();
	{
		Clear();
		AddHeader("S fetion.com.cn SIP-C/4.0");
		AddHeader("F: "+fxno);
		AddHeader("I: "+i2s(i));
		AddHeader("Q: 1 S");
		AddHeader("N: StartChat");
		return Send();
	}

	AStr scr(AStr fxno,int i,AStr msg) //StartChat Register to Server
	{
		Clear();
		AddHeader("R fetion.com.cn SIP-C/4.0");
		AddHeader("F: "+fxno);
		AddHeader("I: "+i2s(i));
		AddHeader("Q: 2 R");
		AddHeader("A: TICKS auth=\""+msg.get("credential=\"","\"")+"\"");
		AddHeader("K: text/plain");
		//AddHeader("C: text/html-fragment");
		AddHeader("K: multiparty");
		return Send();
	}

	AStr sci(AStr fxno,int i,AStr dst) //StartChat InviteBuddy
	{
		Clear();
		AddHeader("S fetion.com.cn SIP-C/4.0");
		AddHeader("F: "+fxno);
		AddHeader("I: "+i2s(i));
		AddHeader("Q: 3 S");
		AddHeader("N: InviteBuddy");
		
		SetContent("<args><contacts><contact uri=\""+dst+"\" /></contacts></args>");
		return Send();
	}

	AStr kal(AStr fxno,int q)
	{
		Clear();
		AddHeader("R fetion.com.cn SIP-C/4.0");
		AddHeader("F: "+fxno);
		AddHeader("I: 1 ");
		AddHeader("Q: "+i2s(q)+" R");
		AddHeader("N: KeepAlive");

		SetContent("<args><credentials domains=\"fetion.com.cn;m161.com.cn\"/></args>");//;m161.com.cn;www.ikuwa.cn;games.fetion.com.cn;turn.fetion.com.cn;pos.fetion.com.cn;ent.fetion.com.cn;mms.fetion.com.cn
		return Send();
	}

	AStr kcb(AStr fxno,int i,int q)	//Keep Connection Busy
	{
		Clear();
		AddHeader("O fetion.com.cn SIP-C/4.0");
		AddHeader("F: "+fxno);
		AddHeader("I: "+i2s(i));
		AddHeader("Q: "+i2s(q)+" O");
		AddHeader("N: KeepConnectionBusy");
		return Send();
	}
	AStr br(AStr msg)	//Keep Connection Busy
	{
		Clear();
		AddHeader("SIP-C/4.0 200 OK");
		AddHeader("T: "+msg.get("T: ","\r\n"));
		AddHeader("I: "+msg.get("I: ","\r\n"));
		AddHeader("Q: "+msg.get("Q: "," ")+" B");
		return Send();
	}
};

